package com.happy.core.util;


import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 微信昵称emoji处理工具类
 *
 * @author java
 */
public class EmotionUtil {

    /**
     * 检测是否有emoji字符
     *
     * @return 一旦含有就抛出
     */
    public static boolean containsEmoji(String source) {
        if (source == null || source.trim().equals("")) {
            return false;
        }

        int len = source.length();

        for (int i = 0; i < len; i++) {
            char codePoint = source.charAt(i);

            if (!isEmojiCharacter(codePoint)) {
                //do nothing，判断到了这里表明，确认有表情字符
                return true;
            }
        }

        return false;
    }

    /**
     * 判断是否emoji字符
     * TODO 也需要扩展emoji表情的判断区间
     *
     * @return true:不是emoji字符，false:是emoji字符
     */
    private static boolean isEmojiCharacter(char codePoint) {
        return (codePoint == 0x0) ||
                (codePoint == 0x9) ||
                (codePoint == 0xA) ||
                (codePoint == 0xD) ||
                ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) ||
                ((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) ||
                ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
    }

    /**
     * 过滤emoji 或者 其他非文字类型的字符，将其替换为*
     */
    public static String filterEmoji(String source) {
        return filterEmoji(source, "*");
    	/*
        if (!containsEmoji(source)) {
            return source;//如果不包含，直接返回
        }
        //到这里铁定包含
        StringBuilder buf = null;

        int len = source.length();

        for (int i = 0; i < len; i++) {
            char codePoint = source.charAt(i);

            if (isEmojiCharacter(codePoint)) {
                if (buf == null) {
                    buf = new StringBuilder(source.length());
                }

                buf.append(codePoint);
            } else {
            }
        }

        if (buf == null) {
            return source;//如果没有找到 emoji表情，则返回源字符串
        } else {
            if (buf.length() == len) {//这里的意义在于尽可能少的toString，因为会重新生成字符串
                buf = null;
                return source;
            } else {
                return buf.toString();
            }
        }
        */
    }

    /**
     * 过滤emoji 或者 其他非文字类型的字符
     *
     * @param source 字符串
     */
    public static String filterEmoji(String source, String replace) {

        if (source == null) return source;
        Pattern emoji = Pattern.compile("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\ud83e\udd00-\ud83e\udfff]|[\u2600-\u27ff]",
                Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);
//        Pattern emoji = Pattern.compile("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]",
//                Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);
        Matcher emojiMatcher = emoji.matcher(source);
        if (emojiMatcher.find()) {
            source = emojiMatcher.replaceAll(replace);
            return source;
        }

        return source;
    }

    /**
     * 转换emoji 或者 其他非文字类型的字符
     * 将emoji字符转换为unicode编码，并使用[]包裹起来
     * 例如，字符串为"你好#{em}"，其中#{em}代表一个emoji字符,如果emoji的unicode编码为\ud83d，经过转换后的字符串为"你好[\ud83d]"
     *
     * @param source 字符串
     */
    public static String formatEmoji(String source) {

        if (source == null) return source;

        Pattern emoji = Pattern.compile("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\ud83e\udd00-\ud83e\udfff]|[\u2600-\u27ff]",
                Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);
//        Pattern emoji = Pattern.compile("[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]",
//                Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);
        Matcher emojiMatcher = emoji.matcher(source);
        if (emojiMatcher.find()) {
            StringBuilder builder = new StringBuilder();
            String last = null;
            for (int i = 0; i < source.length(); i++) {
                String s = String.valueOf(source.charAt(i));
                String unicide = string2Unicode(s);
                if ("\\ud83c".equals(unicide) || "\\ud83d".equals(unicide) || "\\ud83e".equals(unicide) || "\\u2600".equals(unicide)) {
                    builder.append("[" + unicide + "]");
                    last = s;
                    continue;
                }
                String st = last == null ? s : (last + s);
                Matcher matcher = emoji.matcher(st);
                if (matcher.find()) {
                    builder.append("[" + unicide + "]");
                } else {
                    builder.append(s);
                }

                last = null;
            }
            return builder.toString();
        }

        return source;
    }

    /**
     * 将字符串中带有unicode编码的字符还原为字符串
     * [\u0000]格式表示是unicode编码字符
     * 例如，字符串为"你好[\u554a]"，转换为"你好啊"
     */
    public static String parseEmoji(String source) {

        if (source == null) return source;

        StringBuilder builder = new StringBuilder();

        Pattern unicodePattern = Pattern.compile("[\u0000-\uffff]", Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);

        while (source.contains("[\\u") && source.contains("]")) {
            int begin = source.indexOf("[\\u");
            int end = source.indexOf("]");
            if (begin > 0 || begin > end) {// ]在[\\u之前
                String str = source.substring(0, begin);
                source = source.substring(begin);
                builder.append(str);
            } else {
                String unicode = source.substring(begin + 1, end);//[]之间的字符
                source = source.substring(end + 1);
                Matcher matcher = unicodePattern.matcher(unicode);
                if (matcher.find()) {//是unicode编码
                    String str = unicode2String(unicode);
                    builder.append(str);
                } else {//非unicode编码
                    builder.append("[" + unicode + "]");
                }
            }
        }

        builder.append(source);

        return builder.toString();
    }

    public static String unicode2String(String unicode) {

        StringBuffer string = new StringBuffer();

        String[] hex = unicode.split("\\\\u");

        for (int i = 1; i < hex.length; i++) {

            // 转换出每一个代码点
            int data = Integer.parseInt(hex[i], 16);

            // 追加成string
            string.append((char) data);
        }

        return string.toString();
    }

    public static String string2Unicode(String string) {
        StringBuffer unicode = new StringBuffer();
        for (int i = 0; i < string.length(); i++) {
            // 取出每一个字符
            char c = string.charAt(i);
            // 转换为unicode
            unicode.append("\\u" + Integer.toHexString(c));
        }
        return unicode.toString();
    }

}